package com.zhentao.controller;

import com.zhentao.config.MinioConfig;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.errors.MinioException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 聊天视频上传控制器
 * 专门处理聊天中的视频上传功能
 * 
 * @author zhentao
 * @version 1.0
 * @since 2025-09-07
 */
@RestController
@RequestMapping("/api/chat")
//@CrossOrigin(origins = "*")
public class ChatVideoController {

    private static final Logger logger = LoggerFactory.getLogger(ChatVideoController.class);

    private static final String CHAT_VIDEO_BUCKET = "chat-videos";

    @Autowired
    private MinioConfig minioConfig;

    // 聊天视频相关配置常量
    private static final long MAX_FILE_SIZE = 100 * 1024 * 1024; // 100MB
    private static final String[] ALLOWED_TYPES = {
        "video/mp4", "video/avi", "video/mov", "video/wmv", "video/flv",
        "video/webm", "video/mkv", "video/3gp", "video/m4v"
    };

    /**
     * 创建MinIO客户端
     */
    private MinioClient createMinioClient() {
        return MinioClient.builder()
                .endpoint(minioConfig.getEndpoint())
                .credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
                .build();
    }

    /**
     * 上传聊天视频
     * @param fromUser 发送者用户名
     * @param toUser 接收者用户名（可选，群聊时为群ID）
     * @param file 视频文件
     * @return 上传结果
     */
    @PostMapping("/video/upload")
    public ResponseEntity<Map<String, Object>> uploadChatVideo(
            @RequestParam("fromUser") String fromUser,
            @RequestParam(value = "toUser", required = false) String toUser,
            @RequestParam("file") MultipartFile file) {
        
        logger.info("上传聊天视频，发送者: {}, 接收者: {}, 文件名: {}, 文件大小: {} bytes", 
                fromUser, toUser, file.getOriginalFilename(), file.getSize());
        
        Map<String, Object> response = new HashMap<>();
        
        try {
            // 基础验证
            if (fromUser == null || fromUser.trim().isEmpty()) {
                logger.warn("发送者用户名为空");
                return buildErrorResponse("INVALID_USER", "发送者用户名不能为空", HttpStatus.BAD_REQUEST);
            }
            
            if (file == null || file.isEmpty()) {
                logger.warn("上传文件为空");
                return buildErrorResponse("EMPTY_FILE", "请选择要上传的视频", HttpStatus.BAD_REQUEST);
            }
            
            // 文件大小验证
            if (file.getSize() > MAX_FILE_SIZE) {
                logger.warn("文件大小超限: {} bytes", file.getSize());
                return buildErrorResponse("FILE_TOO_LARGE", 
                    String.format("视频大小不能超过%dMB", MAX_FILE_SIZE / (1024 * 1024)), 
                    HttpStatus.BAD_REQUEST);
            }
            
            // 文件类型验证
            String contentType = file.getContentType();
            boolean isValidType = false;
            for (String allowedType : ALLOWED_TYPES) {
                if (allowedType.equals(contentType)) {
                    isValidType = true;
                    break;
                }
            }
            
            if (!isValidType) {
                logger.warn("不支持的文件类型: {}", contentType);
                return buildErrorResponse("INVALID_FILE_TYPE", 
                    "只支持MP4、AVI、MOV、WMV、FLV、WEBM、MKV、3GP、M4V格式的视频", 
                    HttpStatus.BAD_REQUEST);
            }
            
            // 生成唯一文件名
            String originalFilename = file.getOriginalFilename();
            logger.info("原始文件名: {}", originalFilename);
            
            String fileExtension = "";
            if (originalFilename != null && originalFilename.contains(".")) {
                fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            }
            
            // 文件命名规则：chat_发送者_时间戳_随机UUID.扩展名
            String objectName = String.format("chat_%s_%d_%s%s",
                fromUser, System.currentTimeMillis(), UUID.randomUUID().toString().substring(0, 8), fileExtension);
            logger.info("生成的对象名: {}", objectName);
            
            // 创建MinIO客户端并上传文件
            MinioClient minioClient = createMinioClient();

            // 检查桶是否存在，不存在则创建
            try {
                boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(CHAT_VIDEO_BUCKET).build());
                if (!bucketExists) {
                    logger.info("桶 {} 不存在，正在创建...", CHAT_VIDEO_BUCKET);
                    minioClient.makeBucket(MakeBucketArgs.builder().bucket(CHAT_VIDEO_BUCKET).build());
                    logger.info("桶 {} 创建成功", CHAT_VIDEO_BUCKET);
                }
            } catch (Exception e) {
                logger.warn("检查或创建桶时出现异常: {}", e.getMessage());
            }

            try (InputStream inputStream = file.getInputStream()) {
                String chatVideosBucket = minioConfig.getChatVideosBucket();
                logger.info("开始上传文件到MinIO，桶名: {}, 对象名: {}", chatVideosBucket, objectName);

                minioClient.putObject(
                    PutObjectArgs.builder()
                        .bucket(chatVideosBucket)
                        .object(objectName)
                        .stream(inputStream, file.getSize(), -1)
                        .contentType(contentType)
                        .build()
                );

                logger.info("文件上传到MinIO成功，对象名: {}", objectName);

                // 构建视频访问URL
                String videoUrl = minioConfig.getEndpoint() + "/" + chatVideosBucket + "/" + objectName;
                
                // 构建响应数据
                Map<String, Object> data = new HashMap<>();
                data.put("fromUser", fromUser);
                data.put("toUser", toUser);
                data.put("videoUrl", videoUrl);
                data.put("objectName", objectName);
                data.put("uploadTime", new Date());
                data.put("fileSize", file.getSize());
                data.put("contentType", contentType);
                data.put("originalFilename", originalFilename);
                
                response.put("success", true);
                response.put("message", "视频上传成功");
                response.put("code", "SUCCESS");
                response.put("data", data);
                
                logger.info("聊天视频上传成功，发送者: {}, 视频URL: {}", fromUser, videoUrl);
                return ResponseEntity.ok(response);
                
            }
            
        } catch (MinioException e) {
            logger.error("MinIO操作异常，发送者: {}", fromUser, e);
            return buildErrorResponse("MINIO_ERROR", "文件存储服务异常: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
        } catch (InvalidKeyException | NoSuchAlgorithmException e) {
            logger.error("MinIO认证异常，发送者: {}", fromUser, e);
            return buildErrorResponse("AUTH_ERROR", "存储服务认证失败", HttpStatus.INTERNAL_SERVER_ERROR);
        } catch (IOException e) {
            logger.error("文件读取异常，发送者: {}", fromUser, e);
            return buildErrorResponse("FILE_READ_ERROR", "文件读取失败", HttpStatus.INTERNAL_SERVER_ERROR);
        } catch (Exception e) {
            logger.error("聊天视频上传时发生异常，发送者: {}", fromUser, e);
            return buildErrorResponse("INTERNAL_ERROR", "视频上传失败", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 构建错误响应
     */
    private ResponseEntity<Map<String, Object>> buildErrorResponse(String code, String message, HttpStatus status) {
        Map<String, Object> response = new HashMap<>();
        response.put("success", false);
        response.put("code", code);
        response.put("message", message);
        response.put("data", null);
        return ResponseEntity.status(status).body(response);
    }
}
